﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;

namespace BarotraumaModTextExtract
{
    class Program
    {
        static XDocument xml目标 = null;
        static XDocument xml记录原版重复 = null;
        static XDocument xml原版 = null;

        static void Main(string[] args)
        {
            if (args.Count() >= 3)
            {
                string xml目标路径 = args[1];
                GetOrAddXml(xml目标路径, out xml目标);

                string xml记录原版重复路径 = xml目标路径.Insert(xml目标路径.LastIndexOf("."), ".Vanilla");
                if (args.Count() >= 4)
                {
                    string vanillaXml路径 = args[3];
                    if (File.Exists(vanillaXml路径))
                    {
                        xml原版 = XDocument.Load(vanillaXml路径);
                        GetOrAddXml(xml记录原版重复路径, out xml记录原版重复);
                    }
                }

                List<string> files源 = new List<string>();
                ParseDirectory(args[0], files源);
                Console.WriteLine($"找到{files源.Count()}个XML文件,开始提取文本");

                foreach (var path in files源)
                {
                    Console.Write($"处理 {path} ");
                    XDocument xmls;
                    try
                    {
                        xmls = XDocument.Load(path);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine();
                        Console.WriteLine($"出错: {ex.ToString()} ");
                        continue;
                    }
                    var xElements = xmls.Descendants("Afflictions")?.FirstOrDefault()?.Elements();
                    if (xElements == null || xElements.Count() == 0)
                    {
                        xElements = xmls.Descendants("Affliction");
                    }
                    if (xElements?.Count() > 0)
                    {
                        foreach (var xe in xElements)
                        {
                            XElement item;
                            if (xe.Name == "Override")
                            {
                                item = xe.Elements().First();
                            }
                            else
                            {
                                item = xe;
                            }
                            string identifier;
                            if (item.Attributes("identifier").Any())
                            {
                                identifier = item.Attribute("identifier").Value;
                            }
                            else
                            {
                                continue;
                            }

                            GetAttrSetOrAddElement(item, identifier, "name", "afflictionname");
                            GetAttrSetOrAddElement(item, identifier, "description", "afflictiondescription");
                            GetAttrSetOrAddElement(item, identifier, "causeofdeathdescription", "causeofdeathdescription");
                            GetAttrSetOrAddElement(item, identifier, "selfcauseofdeathdescription", "afflictioncauseofdeathself");

                        }
                    }

                    xElements = xmls.Descendants("Character");
                    if (xElements?.Count() > 0)
                    {
                        foreach (var xe in xElements)
                        {
                            XElement item;
                            if (xe.Name == "Override")
                            {
                                item = xe.Elements().First();
                            }
                            else
                            {
                                item = xe;
                            }
                            string identifier;
                            if (item.Attributes("speciesname").Any())
                            {
                                identifier = item.Attribute("speciesname").Value;
                            }
                            else
                            {
                                continue;
                            }

                            GetAttrSetOrAddElement(item, identifier, "displayname", "character");
                        }
                    }

                    xElements = xmls.Descendants("Missions")?.FirstOrDefault()?.Elements();
                    if (xElements == null || xElements.Count() == 0)
                    {
                        xElements = xmls.Descendants("Mission");
                    }
                    if (xElements?.Count() > 0)
                    {
                        foreach (var xe in xElements)
                        {
                            XElement item;
                            if (xe.Name == "Override")
                            {
                                item = xe.Elements().First();
                            }
                            else
                            {
                                item = xe;
                            }
                            string identifier;
                            if (item.Attributes("identifier").Any())
                            {
                                identifier = item.Attribute("identifier").Value;
                            }
                            else
                            {
                                continue;
                            }

                            GetAttrSetOrAddElement(item, identifier, "name", "missionname");
                            GetAttrSetOrAddElement(item, identifier, "description", "missiondescription");
                            GetAttrSetOrAddElement(item, identifier, "sonarlabel", "missionsonarlabel");
                            GetAttrSetOrAddElement(item, identifier, "successmessage", "missionsuccess");

                            var messages = item.Elements("message");
                            for (int i = 0; i < messages.Count(); i++)
                            {
                                GetAttrSetOrAddElement(messages.ElementAt(i), identifier, "header", "missionheader" + i);
                                GetAttrSetOrAddElement(messages.ElementAt(i), identifier, "text", "missionmessage" + i);
                            }

                        }
                    }

                    xElements = xmls.Descendants("Items")?.FirstOrDefault()?.Elements();
                    if (xElements == null || xElements.Count() == 0)
                    {
                        xElements = xmls.Descendants("Item");
                    }
                    if (xElements?.Count() > 0)
                    {
                        foreach (var xe in xElements)
                        {
                            XElement item;
                            if (xe.Name == "Override")
                            {
                                item = xe.Elements().First();
                            }
                            else
                            {
                                item = xe;
                            }
                            string identifier;
                            if (item.Attributes("identifier").Any())
                            {
                                identifier = item.Attribute("identifier").Value;
                            }
                            else
                            {
                                continue;
                            }

                            GetAttrSetOrAddElement(item, identifier, "name", "entityname");
                            GetAttrSetOrAddElement(item, identifier, "description", "entitydescription");
                        }
                    }

                    xElements = xmls.Descendants("UpgradeModules")?.FirstOrDefault()?.Elements();
                    if (xElements == null || xElements.Count() == 0)
                    {
                        xElements = xmls.Descendants("UpgradeModule");
                    }
                    if (xElements?.Count() > 0)
                    {
                        foreach (var xe in xElements)
                        {
                            XElement item;
                            if (xe.Name == "Override")
                            {
                                item = xe.Elements().First();
                            }
                            else
                            {
                                item = xe;
                            }
                            string identifier;
                            if (item.Attributes("identifier").Any())
                            {
                                identifier = item.Attribute("identifier").Value;
                            }
                            else
                            {
                                continue;
                            }

                            GetAttrSetOrAddElement(item, identifier, "name", "upgradename");
                            GetAttrSetOrAddElement(item, identifier, "description", "upgradedescription");
                        }
                    }

                    if (args[2] == "1")
                    {
                        xmls.Save(path);
                    }
                    xml目标.Save(xml目标路径);

                    if (xml原版 != null)
                    {
                        if (xml记录原版重复.Root.HasElements)
                        {
                            xml记录原版重复.Save(xml记录原版重复路径);
                        }
                    }

                    Console.Write("完成");
                    Console.WriteLine();
                }
            }
            else
            {
                Console.WriteLine("参数不正确,需要3-4个参数,顺序如下");
                Console.WriteLine("MOD目录 文本保存的XML路径 是否清空MOD文本(1就是清空) 官方XML目录(排除游戏原版文本)");
                Console.WriteLine("示例:");
                Console.WriteLine("BarotraumaModTextExtract.exe \"..\\EK Armory\" EKArmory.xml 1 \"..\\..\\Content\\Texts\\SimplifiedChinese\\SimplifiedChineseVanilla.xml\"");
            }
        }

        private static void GetOrAddXml(string path, out XDocument document)
        {
            if (File.Exists(path))
            {
                document = XDocument.Load(path);
            }
            else
            {
                document = new XDocument();
                XElement infotexts = new XElement("infotexts");
                infotexts.SetAttributeValue("language", "Simplified Chinese");
                infotexts.SetAttributeValue("nowhitespace", "true");
                infotexts.SetAttributeValue("translatedname", "中文(简体)");
                document.Add(infotexts);
            }
        }

        /// <summary>
        /// 根据来源元素的指定属性提取文本,提取的文本生成改为指定元素插入新的XML
        /// </summary>
        /// <param name="item">文本来源名</param>
        /// <param name="identifier">文本来源元素名</param>
        /// <param name="attributeName">文本来源属性名</param>
        /// <param name="newName">保存的元素名前缀</param>
        private static void GetAttrSetOrAddElement(XElement item, string identifier, string attributeName, string newName)
        {
            string[] ids = identifier.Split(',');
            var xAttribute = item.Attribute(attributeName);
            for (int i = 0; i < ids.Length; i++)
            {
                if (xAttribute != null && !string.IsNullOrWhiteSpace(xAttribute.Value))
                {
                    XElement newXE = new XElement($"{newName}.{ids[i]}", xAttribute.Value);

                    XElement vanillaXE = xml原版.Root.Element(newXE.Name);

                    if (vanillaXE == null)
                    {
                        XElement oldXE = xml目标.Root.Element(newXE.Name);
                        if (oldXE == null)
                        {
                            xml目标.Root.Add(newXE);
                        }
                        else
                        {
                            if (string.IsNullOrWhiteSpace(oldXE.Value))
                            {
                                oldXE.Value = newXE.Value;
                            }
                        }
                    }
                    else
                    {
                        var vSxml = xml记录原版重复.Root.Element(newXE.Name);
                        if (vSxml == null)
                        {
                            xml记录原版重复.Root.Add(newXE);
                        }
                    }

                    xAttribute.Value = "";
                }
            }

        }

        static void ParseDirectory(string path, List<string> list)
        {

            string[] dirs = Directory.GetDirectories(path);//得到子目录
            IEnumerator iter = dirs.GetEnumerator();
            while (iter.MoveNext())
            {
                string str = (string)(iter.Current);
                ParseDirectory(str, list);
            }
            string[] files = Directory.GetFiles(path, "*.xml");
            if (files.Length > 0)
            {
                list.AddRange(files);
            }
        }
    }
}
